﻿using System;
using UnityEngine;
using Object = UnityEngine.Object;

namespace TPF.ObjectCache
{
    public class GameObjectPool : IDisposable
    {
        private PoolCore _poolCore;

        internal PoolCore PoolCore
        {
            get { return _poolCore; }
        }

        public string Tag
        {
            get { return _poolCore.PoolTag; }
        }

        /// <summary>
        /// 同一帧异步回调的数量限制
        /// </summary>
        /// <remarks>详见PoolCore.MaxAsyncCallbackOneFrame的注释</remarks>
        public int MaxAsyncCallbackOneFrame
        {
            get { return PoolCore.MaxAsyncCallbackOneFrame; }
            set { PoolCore.MaxAsyncCallbackOneFrame = value; }
        }

        /// <summary>
        /// 构造一个GameObjectPool对象，自动创建关联的PoolCore
        /// </summary>
        /// <param name="tag">对象池的标签</param>
        /// <param name="recycleMethod">指定对象回收方式，默认为<see cref="PoolRecycleMethodDeactive"/></param>
        public GameObjectPool(string tag, PoolRecycleMethod recycleMethod = null)
        {
            var poolCoreGameObject = new GameObject(tag);
            Object.DontDestroyOnLoad(poolCoreGameObject);

            _poolCore = poolCoreGameObject.AddComponent<PoolCore>();
            _poolCore.Initialize(tag);

            // 如果没有传入Recycle method，则使用默认的
            if (recycleMethod == null)
            {
                recycleMethod = new PoolRecycleMethodDeactive();
            }
            _poolCore.SetRecycleMethod(recycleMethod);

            MaxAsyncCallbackOneFrame = 3; // 默认值
        }

        /// <summary>
        /// 将指定规则对象应用于对象池，无法应用相同类型的规则多次
        /// </summary>
        /// <param name="rule"></param>
        public void ApplyRule(PoolRule rule)
        {
            _poolCore.ApplyRule(rule);
        }

        /// <summary>
        /// 获取一个对象，同步方法
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public GameObject Get(string key)
        {
            return _poolCore.Get(key);
        }

        /// <summary>
        /// 获取一个对象，异步方法
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public PoolRequest GetAsync(string key)
        {
            return _poolCore.GetAsync(key);
        }

        /// <summary>
        /// 回收对象
        /// 作用对象必须是通过Get/GetAsync获得的对象
        /// </summary>
        /// <param name="obj"></param>
        public void Recycle(GameObject obj)
        {
            _poolCore.Recycle(obj);
        }

        /// <summary>
        /// 清除对象池
        /// 包括所有激活的对象，池中对象及模板
        /// </summary>
        public void Clear()
        {
            _poolCore.Clear();
        }

        /// <summary>
        /// 打印出当前对象池的状态
        /// </summary>
        public void Dump()
        {
            _poolCore.Dump();
        }

        /// <summary>
        /// 释放掉对象池引用的资源，释放之后对象池将不再可用
        /// </summary>
        public void Dispose()
        {
            _poolCore.Clear();
            Object.Destroy(_poolCore);
            _poolCore = null;
        }
    }
}